﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;

namespace Utils
{
    public static class MapperHelper
    {

        public static IEnumerable<T> Mappers<T>(this IEnumerable source) where T : class
        {
            foreach (var item in source)
            {
                yield return item.Mapper<T>(null);
            }
        }

        public static IEnumerable<T> Mappers<S, T>(this IEnumerable<S> source, Func<S, object> append) where T : class
        {
            foreach (var item in source)
            {
                yield return item.Mapper<T>(append?.Invoke(item));
            }
        }

        public static IEnumerable<T> MappersWithoutZero<T>(this IEnumerable source) where T : class
        {
            foreach (var item in source)
            {
                yield return item.MapperWithoutZero<T>(null);
            }
        }

        public static IEnumerable<T> MappersWithoutZero<S, T>(this IEnumerable<S> source, Func<S, object> append) where T : class
        {
            foreach (var item in source)
            {
                yield return item.MapperWithoutZero<T>(append?.Invoke(item));
            }
        }
        /// <summary>
        /// 转换
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="arg"></param>
        /// <returns></returns>
        public static T Mapper<T>(this object arg, object append = null) where T : class
        {
            return Assign<T>(null, false, arg, append);
        }

        public static T MapperWithoutZero<T>(this object arg, object append = null) where T : class
        {
            return Assign<T>(null, true, arg, append);
        }
        public static T Assign<T>(this T source, bool withoutZero, params object[] args) where T : class
        {
            Type t = typeof(T);
            if (args.Length == 0)
                return source;
            if (source == null)
            {
                source = Activator.CreateInstance<T>();
            }
            PropertyInfo[] ps = t.GetProperties(BindingFlags.Instance | BindingFlags.Public);
            foreach (var @obj in args)
            {
                if (@obj == null)
                    continue;
                Type type = @obj.GetType();
                foreach (var p in ps)
                {
                    if (p.CanWrite)
                    {
                        PropertyInfo p1 = type.GetProperty(p.Name, BindingFlags.IgnoreCase | BindingFlags.Instance | BindingFlags.Public);
                        if (p1 != null && p1.CanRead)
                        {
                            var value = p1.GetValue(@obj, null);

                            if (value != null && p.PropertyType.TryChangeType(ref value))
                            {
                                if (withoutZero && 0.Equals(value))
                                {
                                    continue;
                                }
                                p.SetValue(source, value, null);
                            }
                        }
                    }
                }
            }
            return source;
        }



    }
}
